module axi2apb_bridge (
    input                  s_axi_aclk         ,
    input                  s_axi_aresetn      ,
    input  [31 : 0]        s_axi_awaddr       ,
    input                  s_axi_awvalid      ,
    output                 s_axi_awready      ,
    input  [31 : 0]        s_axi_wdata        ,
    input                  s_axi_wvalid       ,   
    output                 s_axi_wready       ,  
    output [1 : 0]         s_axi_bresp        ,
    output                 s_axi_bvalid       ,  
    input                  s_axi_bready       ,   
    input  [31 : 0]        s_axi_araddr       ,
    input                  s_axi_arvalid      ,   
    output                 s_axi_arready      ,  
    output [31 : 0]        s_axi_rdata        ,
    output [1 : 0]         s_axi_rresp        ,
    output                 s_axi_rvalid       ,  
    input                  s_axi_rready       ,
    output                 soft_clk_27dr_reset   ,
    output                 ctrl_led   
    //  
    // output [15 : 0]        paddr              ,
    // output                 psel_phy           ,
    // output                 penable            ,  
    // output                 pwrite             ,  
    // output [31 : 0]        pwdata             ,
    // input  [31 : 0]        prdata_phy         ,
);
`include "xczu27dr_def.v"

wire           psel       ;
wire           psel_top   ;
wire [15 : 0]  paddr      ;
wire           penable    ;
wire           pwrite     ;
wire [31 : 0]  pwdata     ;

wire [31:0]    prdata     ;
reg  [31:0]    prdata_top ;
reg  [2:0]     top_reg_0  ;
reg  [1 : 0]   top_reg_1  ;
wire [31:0]    paddr_full ;
wire [31:0]    usr_access_data;

//address map : 
// top    : 0xA0010000 - 0xA00100FC

axi_apb_bridge_0 u_axi_apb_bridge_0 (
  .s_axi_aclk   (  s_axi_aclk     ),   // input wire s_axi_aclk
  .s_axi_aresetn(  s_axi_aresetn  ),   // input wire s_axi_aresetn
  .s_axi_awaddr (  s_axi_awaddr   ),   // input wire [31 : 0] s_axi_awaddr
  .s_axi_awvalid(  s_axi_awvalid  ),   // input wire s_axi_awvalid
  .s_axi_awready(  s_axi_awready  ),   // output wire s_axi_awready
  .s_axi_wdata  (  s_axi_wdata    ),   // input wire [31 : 0] s_axi_wdata
  .s_axi_wvalid (  s_axi_wvalid   ),   // input wire s_axi_wvalid
  .s_axi_wready (  s_axi_wready   ),   // output wire s_axi_wready
  .s_axi_bresp  (  s_axi_bresp    ),   // output wire [1 : 0] s_axi_bresp
  .s_axi_bvalid (  s_axi_bvalid   ),   // output wire s_axi_bvalid
  .s_axi_bready (  s_axi_bready   ),   // input wire s_axi_bready
  .s_axi_araddr (  s_axi_araddr   ),   // input wire [31 : 0] s_axi_araddr
  .s_axi_arvalid(  s_axi_arvalid  ),   // input wire s_axi_arvalid
  .s_axi_arready(  s_axi_arready  ),   // output wire s_axi_arready
  .s_axi_rdata  (  s_axi_rdata    ),   // output wire [31 : 0] s_axi_rdata
  .s_axi_rresp  (  s_axi_rresp    ),   // output wire [1 : 0] s_axi_rresp
  .s_axi_rvalid (  s_axi_rvalid   ),   // output wire s_axi_rvalid
  .s_axi_rready (  s_axi_rready   ),   // input wire s_axi_rready
  .m_apb_paddr  (   paddr_full    ),   // output wire [31 : 0] m_apb_paddr
  .m_apb_psel   (   psel          ),   // output wire [0 : 0] m_apb_psel
  .m_apb_penable(   penable       ),   // output wire m_apb_penable
  .m_apb_pwrite (   pwrite        ),   // output wire m_apb_pwrite
  .m_apb_pwdata (   pwdata        ),   // output wire [31 : 0] m_apb_pwdata
  .m_apb_pready (  1'b1           ),   // input wire [0 : 0] m_apb_pready
  .m_apb_prdata (  prdata         ),   // input wire [31 : 0] m_apb_prdata
  .m_apb_pslverr(  1'b0           )    // input wire [0 : 0] m_apb_pslverr
); 

assign paddr     = paddr_full[`APB_ADD_WIDTH-1:0] ;
assign psel_top  = psel & paddr >= `TOP_APB_ADD_S  & paddr <= `TOP_APB_ADD_E;
// assign psel_phy  = psel & paddr >= `PHY_APB_ADD_S  & paddr <= `PHY_APB_ADD_E;

// assign prdata = {32{psel_top}} & prdata_top |
//                 {32{psel_phy}} & prdata_phy ;
assign prdata = {32{psel_top}} & prdata_top ;
                
//===============================
//  TOP REGISTERS                
//===============================
always @(posedge s_axi_aclk ) 
    if (~s_axi_aresetn)
       begin
         top_reg_0 <= 'h0;
         top_reg_1 <= 'h0;
       end                
    else if (psel_top & penable & pwrite)
       begin
          case(paddr)
          'h000 : top_reg_0 <= pwdata[2:0];
          'h004 : top_reg_1 <= pwdata[1:0];
          endcase      
       end
 
always @( * )
begin
        prdata_top   = 'd0; 	
    if (psel_top & penable & ~pwrite)
        case(paddr)
        'h000  :  prdata_top   = {29'b0 , top_reg_0};
        'h004  :  prdata_top   = {30'b0 , top_reg_1};
        'h008  :  prdata_top   = usr_access_data;  // code version 1
        default :  prdata_top   = 'd0;
        endcase
    else
        prdata_top   = 'd0;       
end 

assign soft_clk_27dr_reset = top_reg_1[0];
assign ctrl_led            = top_reg_1[1];

USR_ACCESSE2 USR_ACCESSE2_inst (
      .CFGCLK(),       // 1-bit output: Configuration Clock output
      .DATA  (usr_access_data),           // 32-bit output: Configuration Data output
      .DATAVALID()  // 1-bit output: Active high data valid output
   );

endmodule //axi2apb_bridge.v

